home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / cells.c < prev    next >
C/C++ Source or Header  |  1993-03-30  |  12KB  |  589 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #define obstack_chunk_alloc ck_malloc
  20. #define obstack_chunk_free free
  21. #include "obstack.h"
  22. #include "funcdef.h"
  23. #include "sysdef.h"
  24.  
  25. #include "global.h"
  26. #include "cell.h"
  27. #include "eval.h"
  28. #include "errors.h"
  29. #include "lists.h"
  30. #include "format.h"
  31. #include "io-abstract.h"
  32. #include "io-generic.h"
  33. #include "io-term.h"
  34. #include "cmd.h"
  35.  
  36. struct value
  37.   {
  38.     int type;
  39.     union vals x;
  40.   };
  41.  
  42. #define Float    x.c_d
  43. #define String    x.c_s
  44. #define Int    x.c_l
  45. #define Value    x.c_i
  46. #define Rng    x.c_r
  47.  
  48. #define ERROR(x)    \
  49.  {            \
  50.     p->Value=x;    \
  51.     p->type=TYP_ERR;\
  52.     return;        \
  53.  }
  54.  
  55.  
  56. static int
  57. cell (row, col, dowhat, p)
  58.      long row;
  59.      long col;
  60.      char *dowhat;
  61.      struct value *p;
  62. {
  63.   struct func
  64.     {
  65.       char *name;
  66.       int typ;
  67.     };
  68.  
  69.   static struct func cell_funs[] =
  70.   {
  71.     {"row", TYP_INT},
  72.     {"column", TYP_INT},
  73.     {"width", TYP_INT},
  74.     {"lock", TYP_STR},
  75.     {"protection", TYP_STR},
  76.     {"justify", TYP_STR},
  77.     {"alignment", TYP_STR},
  78.     {"fmt", TYP_STR},
  79.     {"format", TYP_STR},
  80.     {"type", TYP_STR},
  81.     {"formula", TYP_STR},
  82.     {"value", 0},
  83.     {0, 0}
  84.   };
  85.  
  86.   CELL *cell_ptr;
  87.   char *strptr;
  88.   struct func *func;
  89.   struct func *f1;
  90.   int n;
  91.  
  92.   n = strlen (dowhat) - 1;
  93.   f1 = 0;
  94.   for (func = cell_funs; func->name; func++)
  95.     if (func->name[0] == dowhat[0]
  96.     && (n == 0 || !strincmp (&(func->name[1]), &dowhat[1], n)))
  97.       {
  98.     if (f1)
  99.       return BAD_INPUT;
  100.     f1 = func;
  101.       }
  102.   if (!f1)
  103.     return BAD_INPUT;
  104.   p->type = f1->typ;
  105.   switch (f1 - cell_funs)
  106.     {
  107.     case 0:
  108.       p->Int = row;
  109.       break;
  110.     case 1:
  111.       p->Int = col;
  112.       break;
  113.     case 2:
  114.       p->Int = get_width (col);
  115.       break;
  116.     case 3:
  117.     case 4:
  118.       cell_ptr = find_cell (row, col);
  119.       p->String = ( (cell_ptr ? GET_LCK (cell_ptr) : default_lock)
  120.            ? "locked"
  121.            : "unlocked");
  122.       break;
  123.     case 5:
  124.     case 6:
  125.       cell_ptr = find_cell (row, col);
  126.       p->String = jst_to_str (cell_ptr ?  GET_JST (cell_ptr) : default_jst); 
  127.       break;
  128.     case 7:
  129.     case 8:
  130.       p->String = fmt_to_str ((cell_ptr = find_cell (row, col)) ? GET_FMT (cell_ptr) : 0);
  131.       break;
  132.     case 9:
  133.       cell_ptr = find_cell (row, col);
  134.       if (cell_ptr)
  135.     switch (GET_TYP (cell_ptr))
  136.       {
  137.       case TYP_FLT:
  138.         p->String = "float";
  139.         break;
  140.       case TYP_INT:
  141.         p->String = "integer";
  142.         break;
  143.       case TYP_STR:
  144.         p->String = "string";
  145.         break;
  146.       case TYP_BOL:
  147.         p->String = "boolean";
  148.         break;
  149.       case TYP_ERR:
  150.         p->String = "error";
  151.         break;
  152.       default:
  153.         p->String = "unknown";
  154.       }
  155.       else
  156.     p->String = "null";
  157.       break;
  158.     case 10:
  159.       cell_ptr = find_cell (row, col);
  160.       if (cell_ptr && (GET_TYP (cell_ptr) || cell_ptr->cell_formula))
  161.     {
  162.       strptr = decomp (row, col, cell_ptr);
  163.       p->String = obstack_alloc (&tmp_mem, strlen (strptr) + 1);
  164.       strcpy (p->String, strptr);
  165.       decomp_free ();
  166.     }
  167.       else
  168.     p->String = "";
  169.       break;
  170.     case 11:
  171.       cell_ptr = find_cell (row, col);
  172.       if (cell_ptr)
  173.     {
  174.       p->type = GET_TYP (cell_ptr);
  175.       p->x = cell_ptr->c_z;
  176.     }
  177.       else
  178.     p->type = 0;
  179.       break;
  180.     default:
  181.       return BAD_INPUT;
  182.     }
  183.   return 0;
  184. }
  185.  
  186.  
  187. static void
  188. do_curcell (p)
  189.      struct value *p;
  190. {
  191.   int tmp;
  192.  
  193.   tmp = cell (curow, cucol, p->String, p);
  194.   if (tmp)
  195.     ERROR (tmp);
  196. }
  197.  
  198. static void
  199. do_my (p)
  200.      struct value *p;
  201. {
  202.   int tmp;
  203.  
  204.   tmp = cell (cur_row, cur_col, p->String, p);
  205.   if (tmp)
  206.     ERROR (tmp);
  207. }
  208.  
  209. /* Note that the second argument may be *anything* including ERROR.  If it is
  210.    error, we find the first occurence of that ERROR in the range */
  211.  
  212. static void
  213. do_member (p)
  214.      struct value *p;
  215. {
  216.   CELLREF crow;
  217.   CELLREF ccol;
  218.   int foundit;
  219.   CELL *cell_ptr;
  220.  
  221.   find_cells_in_range (&(p->Rng));
  222.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  223.     {
  224.       if (GET_TYP (cell_ptr) != (p + 1)->type)
  225.     continue;
  226.       switch ((p + 1)->type)
  227.     {
  228.     case 0:
  229.       foundit = 1;
  230.       break;
  231.     case TYP_FLT:
  232.       foundit = cell_ptr->cell_flt == (p + 1)->Float;
  233.       break;
  234.     case TYP_INT:
  235.       foundit = cell_ptr->cell_int == (p + 1)->Int;
  236.       break;
  237.     case TYP_STR:
  238.       foundit = !strcmp (cell_ptr->cell_str, (p + 1)->String);
  239.       break;
  240.     case TYP_BOL:
  241.       foundit = cell_ptr->cell_bol == (p + 1)->Value;
  242.       break;
  243.     case TYP_ERR:
  244.       foundit = cell_ptr->cell_err == (p + 1)->Value;
  245.       break;
  246.     default:
  247.       foundit = 0;
  248. #ifdef TEST
  249.       panic ("Unknown type (%d) in member", (p + 1)->type);
  250. #endif
  251.     }
  252.       if (foundit)
  253.     {
  254.       no_more_cells ();
  255.       p->Int = 1 + crow - p->Rng.lr + (ccol - p->Rng.lc) * (1 + p->Rng.hr - p->Rng.lr);
  256.       p->type = TYP_INT;
  257.       return;
  258.     }
  259.     }
  260.   p->Int = 0L;
  261.   p->type = TYP_INT;
  262. }
  263.  
  264. static void
  265. do_smember (p)
  266.      struct value *p;
  267. {
  268.   CELLREF crow;
  269.   CELLREF ccol;
  270.   CELL *cell_ptr;
  271.   char *string;
  272.  
  273.   string = (p + 1)->String;
  274.   find_cells_in_range (&(p->Rng));
  275.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  276.     {
  277.       if (((GET_TYP (cell_ptr) == 0) && (string[0] == '\0'))
  278.       || (cell_ptr && (GET_TYP (cell_ptr) == TYP_STR)
  279.           && strstr (string, cell_ptr->cell_str)))
  280.     {
  281.       no_more_cells ();
  282.       p->Int = 1 + (crow - p->Rng.lr)
  283.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  284.       p->type = TYP_INT;
  285.       return;
  286.     }
  287.     }
  288.   p->Int = 0L;
  289.   p->type = TYP_INT;
  290. }
  291.  
  292. static void
  293. do_members (p)
  294.      struct value *p;
  295. {
  296.   CELLREF crow;
  297.   CELLREF ccol;
  298.   CELL *cell_ptr;
  299.   char *string;
  300.  
  301.   string = (p + 1)->String;
  302.   find_cells_in_range (&(p->Rng));
  303.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  304.     {
  305.       if (GET_TYP (cell_ptr) != TYP_STR)
  306.     continue;
  307.       if (strstr (cell_ptr->cell_str, string))
  308.     {
  309.       no_more_cells ();
  310.       p->Int = 1 + (crow - p->Rng.lr)
  311.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  312.       p->type = TYP_INT;
  313.       return;
  314.     }
  315.     }
  316.   p->Int = 0L;
  317.   p->type = TYP_INT;
  318. }
  319.  
  320. static void
  321. do_pmember (p)
  322.      struct value *p;
  323. {
  324.   CELLREF crow;
  325.   CELLREF ccol;
  326.   CELL *cell_ptr;
  327.   char *string;
  328.  
  329.   string = (p + 1)->String;
  330.   find_cells_in_range (&(p->Rng));
  331.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  332.     {
  333.       if ((GET_TYP (cell_ptr) == 0 && string[0] == '\0')
  334.       || (cell_ptr && GET_TYP (cell_ptr) == TYP_STR && !strncmp (string, cell_ptr->cell_str, strlen (cell_ptr->cell_str))))
  335.     {
  336.       no_more_cells ();
  337.       p->Int = 1 + (crow - p->Rng.lr)
  338.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  339.       p->type = TYP_INT;
  340.       return;
  341.     }
  342.     }
  343.   p->Int = 0L;
  344.   p->type = TYP_INT;
  345. }
  346.  
  347. static void
  348. do_memberp (p)
  349.      struct value *p;
  350. {
  351.   CELLREF crow;
  352.   CELLREF ccol;
  353.   CELL *cell_ptr;
  354.   int tmp;
  355.   char *string;
  356.  
  357.   string = (p + 1)->String;
  358.   find_cells_in_range (&(p->Rng));
  359.   tmp = strlen (string);
  360.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  361.     {
  362.       if (GET_TYP (cell_ptr) != TYP_STR)
  363.     continue;
  364.       if (!strncmp (cell_ptr->cell_str, string, tmp))
  365.     {
  366.       no_more_cells ();
  367.       p->Int = 1 + (crow - p->Rng.lr)
  368.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  369.       p->type = TYP_INT;
  370.       return;
  371.     }
  372.     }
  373.   p->Int = 0L;
  374.   p->type = TYP_INT;
  375. }
  376.  
  377. static void
  378. do_hlookup (p)
  379.      struct value *p;
  380. {
  381.  
  382.   struct rng *rng = &((p)->Rng);
  383.   double fltval = (p + 1)->Float;
  384.   long offset = (p + 2)->Int;
  385.  
  386.   CELL *cell_ptr;
  387.   double f;
  388.   CELLREF col;
  389.   CELLREF row;
  390.   char *strptr;
  391.  
  392.   row = rng->lr;
  393.   for (col = rng->lc; col <= rng->hc; col++)
  394.     {
  395.       if (!(cell_ptr = find_cell (row, col)))
  396.     ERROR (NON_NUMBER);
  397.       switch (GET_TYP (cell_ptr))
  398.     {
  399.     case TYP_FLT:
  400.       if (fltval < cell_ptr->cell_flt)
  401.         goto out;
  402.       break;
  403.     case TYP_INT:
  404.       if (fltval < cell_ptr->cell_int)
  405.         goto out;
  406.       break;
  407.     case TYP_STR:
  408.       strptr = cell_ptr->cell_str;
  409.       f = astof (&strptr);
  410.       if (!*strptr && fltval > f)
  411.         goto out;
  412.       else
  413.         ERROR (NON_NUMBER);
  414.     case 0:
  415.     case TYP_BOL:
  416.     case TYP_ERR:
  417.     default:
  418.       ERROR (NON_NUMBER);
  419.     }
  420.     }
  421. out:
  422.   if (col == rng->lc)
  423.     ERROR (OUT_OF_RANGE);
  424.   --col;
  425.   row = rng->lr + offset;
  426.   if (row > rng->hr)
  427.     ERROR (OUT_OF_RANGE);
  428.   cell_ptr = find_cell (row, col);
  429.   if (!cell_ptr)
  430.     {
  431.       p->type = 0;
  432.       p->Int = 0;
  433.     }
  434.   else
  435.     {
  436.       p->type = GET_TYP (cell_ptr);
  437.       p->x = cell_ptr->c_z;
  438.     }
  439. }
  440.  
  441. static void
  442. do_vlookup (p)
  443.      struct value *p;
  444. {
  445.  
  446.   struct rng *rng = &((p)->Rng);
  447.   double fltval = (p + 1)->Float;
  448.   long offset = (p + 2)->Int;
  449.  
  450.   CELL *cell_ptr;
  451.   double f;
  452.   CELLREF col;
  453.   CELLREF row;
  454.   char *strptr;
  455.  
  456.   col = rng->lc;
  457.   for (row = rng->lr; row <= rng->hr; row++)
  458.     {
  459.       if (!(cell_ptr = find_cell (row, col)))
  460.     ERROR (NON_NUMBER);
  461.       switch (GET_TYP (cell_ptr))
  462.     {
  463.     case TYP_FLT:
  464.       if (fltval < cell_ptr->cell_flt)
  465.         goto out;
  466.       break;
  467.     case TYP_INT:
  468.       if (fltval < cell_ptr->cell_int)
  469.         goto out;
  470.       break;
  471.     case TYP_STR:
  472.       strptr = cell_ptr->cell_str;
  473.       f = astof (&strptr);
  474.       if (!*strptr && fltval > f)
  475.         goto out;
  476.       else
  477.         ERROR (NON_NUMBER);
  478.     case 0:
  479.     case TYP_BOL:
  480.     case TYP_ERR:
  481.     default:
  482.       ERROR (NON_NUMBER);
  483.     }
  484.     }
  485. out:
  486.   if (row == rng->lr)
  487.     ERROR (OUT_OF_RANGE);
  488.   --row;
  489.   col = rng->lc + offset;
  490.   if (col > rng->hc)
  491.     ERROR (OUT_OF_RANGE);
  492.  
  493.   cell_ptr = find_cell (row, col);
  494.   if (!cell_ptr)
  495.     {
  496.       p->type = 0;
  497.       p->Int = 0;
  498.     }
  499.   else
  500.     {
  501.       p->type = GET_TYP (cell_ptr);
  502.       p->x = cell_ptr->c_z;
  503.     }
  504. }
  505.  
  506. static void
  507. do_vlookup_str (p)
  508.      struct value *p;
  509. {
  510.  
  511.   struct rng *rng = &((p)->Rng);
  512.   char * key = (p + 1)->String;
  513.   long offset = (p + 2)->Int;
  514.  
  515.   CELL *cell_ptr;
  516.   CELLREF col;
  517.   CELLREF row;
  518.  
  519.   col = rng->lc;
  520.   for (row = rng->lr; row <= rng->hr; row++)
  521.     {
  522.       if (!(cell_ptr = find_cell (row, col)))
  523.     ERROR (NON_NUMBER);
  524.       switch (GET_TYP (cell_ptr))
  525.     {
  526.     case TYP_STR:
  527.       if (!strcmp (key, cell_ptr->cell_str))
  528.         goto out;
  529.       break;
  530.     case 0:
  531.     case TYP_FLT:
  532.     case TYP_INT:
  533.     case TYP_BOL:
  534.     case TYP_ERR:
  535.     default:
  536.       ERROR (NON_NUMBER);
  537.     }
  538.     }
  539. out:
  540.   if (row > rng->hr)
  541.     ERROR (OUT_OF_RANGE);
  542.   col = rng->lc + offset;
  543.   if (col > rng->hc)
  544.     ERROR (OUT_OF_RANGE);
  545.  
  546.   cell_ptr = find_cell (row, col);
  547.   if (!cell_ptr)
  548.     {
  549.       p->type = 0;
  550.       p->Int = 0;
  551.     }
  552.   else
  553.     {
  554.       p->type = GET_TYP (cell_ptr);
  555.       p->x = cell_ptr->c_z;
  556.     }
  557. }
  558.  
  559.  
  560. static void
  561. do_cell (p)
  562.      struct value *p;
  563. {
  564.   int tmp;
  565.  
  566.   tmp = cell (p->Int, (p + 1)->Int, (p + 2)->String, p);
  567.   if (tmp)
  568.     ERROR (tmp);
  569. }
  570.  
  571. struct function cells_funs[] =
  572. {
  573.   {C_FN1 | C_T, X_A1, "S", do_curcell, "curcell"},
  574.   {C_FN1 | C_T, X_A1, "S", do_my, "my"},
  575.   {C_FN3 | C_T, X_A3, "IIS", do_cell, "cell"},
  576.  
  577.   {C_FN2, X_A2, "RA", do_member, "member"},
  578.   {C_FN2, X_A2, "RS", do_smember, "smember"},
  579.   {C_FN2, X_A2, "RS", do_members, "members"},
  580.   {C_FN2, X_A2, "RS", do_pmember, "pmember"},
  581.   {C_FN2, X_A2, "RS", do_memberp, "memberp"},
  582.  
  583.   {C_FN3, X_A3, "RFI", do_hlookup, "hlookup"},
  584.   {C_FN3, X_A3, "RFI", do_vlookup, "vlookup"},
  585.   {C_FN3, X_A3, "RSI", do_vlookup_str, "vlookup_str"},
  586.  
  587.   {0, 0, "", 0, 0},
  588. };
  589.